#include "include/server.h"

Server::Server()
{
    //_serverSocket = -1;
    this->_serverSocket = -1;
}

int Server::InitSocket()
{
    _serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    int res = Connect2DB();
    if (res < 0)
    {
        return -1;
    }
    if (_serverSocket < 0)
    {
        return -1;
    }
    else
    {
        return _serverSocket;
    }
}

int Server::Bind(unsigned short port = 8086)
{
    // printf();
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;
    if (bind(_serverSocket, (const sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("binding failed");
        return -1;
    }
    printf("监听端口:%u", port);
    return 0;
}

int Server::Listen()
{
    if (listen(_serverSocket, 50) < 0)
    {
        perror("listen failed ");
        return -1;
    }
    else
        puts("开启监听");
    return 0;
}

int Server::Accept()
{
    int _clientSockfd = accept(_serverSocket, NULL, NULL);
    if (_clientSockfd < 0)
    {
        perror("accepting failed");
        return -1;
    }
    return _clientSockfd;
}

int Server::IsRun()
{
    if (_serverSocket < 0)
        return false;
    else
        return true;
}

int Server::DealLoginFunction(char *buffer, int socket)
{
    static int id = 404;
    Login *login = (Login *)buffer;
    // puts(login->username);
    // puts(login->password);
    int nbytes = 0;
    char query[1024] = {0};
    Answer answer;
    try
    {

        // // 执行一条查询语句
        Statement *stmt = con->createStatement();
        sprintf(query, "insert into users VALUES(%d,'%s','%s',0)", id++, login->username, login->password);
        // puts(query);
        ResultSet *res = stmt->executeQuery(query);

        delete res;
        delete stmt;
    }
    catch (SQLException &e)
    {
        answer.cmd = CMD_LOGIN_ANSWER;
        answer.answer = false;
        sprintf(answer.reason, "%s", e.what());

        if (e.getErrorCode() == 0)
        {
            answer.answer = true;
            puts("有新用户注册");
            nbytes = send(socket, &answer, MSG_LENGTH, 0);
            if (nbytes < 0)
            {
                perror("sending failed");
                return -1;
            }
        }
        else
        {
            std::cout << "SQLException: " << e.getErrorCode() << " " << e.what() << std::endl;
            nbytes = send(socket, &answer, MSG_LENGTH, 0);
            if (nbytes < 0)
            {
                perror("sending failed");
                return -1;
            }
        }
    }
    if (id == 0)
        return 0;
    try
    {

        // // 执行一条查询语句
        memset(query, 0, 512);
        Statement *stmt = con->createStatement();
        sprintf(query, "create table %s(username VARCHAR(255) PRIMARY KEY,nickname VARCHAR(255),signame VARCHAR(255),offlinemsg VARCHAR(255),msg VARCHAR(1024),frined_join VARCHAR(255))", login->username);
        puts(query);
        ResultSet *res = stmt->executeQuery(query);

        delete res;
        delete stmt;
    }
    catch (SQLException &e)
    {
        std::cout << "SQLException: " << e.getErrorCode() << " " << e.what() << std::endl;
    }
    try
    {

        // // 执行一条查询语句
        memset(query, 0, 512);
        Statement *stmt = con->createStatement();
        // insert into user_info VALUES();
        sprintf(query, "insert into %s VALUES(\"administrator\",\"administator\",\"I am god\",\"/new/prefix1/res/img/01.png\")", login->username);
        puts(query);
        ResultSet *res = stmt->executeQuery(query);

        delete res;
        delete stmt;
    }
    catch (SQLException &e)
    {
        std::cout << "SQLException: " << e.getErrorCode() << " " << e.what() << std::endl;
    }
    // Statement *stmt = con->createStatement();
    // memset(query,0,512);
    // sprintf(query,"create table %s(username VARCHAR(255) PRIMARY KEY,nickname VARCHAR(255),signame VARCHAR(255),offlinemsg VARCHAR(255))",login->username);
    // ResultSet* res = stmt->executeQuery(query);
    // delete res;
    // delete stmt;
    return 0;
}

int Server::DealRequestUserinfo(char *buffer, int socket)
{
    Request *req = (Request *)buffer;
    UserInfo user;
    int nbytes = 0;
    char query[512] = {0};
    try
    {

        // // 执行一条查询语句
        Statement *stmt = con->createStatement();
        sprintf(query, "select * from user_info where username = '%s'", req->username);
        puts(query);
        ResultSet *res = stmt->executeQuery(query);
        while (res->next())
        {

            sprintf(user.username, "%s", res->getString("username").c_str());
            sprintf(user.nickname, "%s", res->getString("nickname").c_str());
            sprintf(user.signature, "%s", res->getString("signature").c_str());
            sprintf(user.path, "%s", res->getString("picture_path").c_str());
        }
        delete res;
        delete stmt;
    }
    catch (SQLException &e)
    {
        std::cout << "SQLException: " << e.getErrorCode() << " " << e.what() << std::endl;
        if (e.getErrorCode() != 0)
        {
            user.req = 0;
            nbytes = send(socket, &user, MSG_LENGTH, 0);
            if (nbytes < 0)
            {
                perror("sending failed");
                return -1;
            }
            else
            {
                printf("%d发送成功\n", nbytes);
            }
            return -1;
        }
    }
    user.req = 1;
    nbytes = send(socket, &user, MSG_LENGTH, 0);
    if (nbytes < 0)
    {
        perror("sending failed");
        return -1;
    }
    else
        printf("ff%d发送成功\n", nbytes);
    puts(user.nickname);
    puts(user.username);
    // puts(user.nickname);
    return 0;
}

int Server::DealRegInfoFunction(char *buffer, int socket)
{
    UserInfo *user = (UserInfo *)buffer;
    char query[1024] = {0};
    Answer answer;

    answer.cmd = CMD_REG_USERINFO_ANSWER;
    int nbytes = 0;

    try
    {
        // // 执行一条查询语句

        Statement *stmt = con->createStatement();
        sprintf(query, "insert into user_info VALUES('%s','%s','%s','%s')", user->username, user->nickname, user->signature, user->path);
        puts(query);
        ResultSet *res = stmt->executeQuery(query);

        delete res;
        delete stmt;
    }
    catch (SQLException &e)
    {
        std::cout << "SQLException: " << e.getErrorCode() << " " << e.what() << std::endl;
        if (e.getErrorCode() != 0)
        {
            answer.answer = false;
            sprintf(answer.reason, "%s", e.what());
            nbytes = send(socket, &answer, MSG_LENGTH, 0);
            if (nbytes < 0)
            {
                perror("sending failed");
                return -1;
            }
            return -1;
        }
    }
    answer.answer = true;
    sprintf(answer.reason, "success");
    nbytes = send(socket, &answer, MSG_LENGTH, 0);
    if (nbytes < 0)
    {
        perror("sending failed");
        return -1;
    }
    else
    {
        printf("%d发送成功\n", nbytes);
    }

    return 0;
}

int Server::DealBigFile(char *buffer, int socket)
{
    FileMsg *mfile = (FileMsg *)buffer;
    int fd = open("./file/1.png", O_CREAT | O_APPEND, 0777);
    if (fd < 0)
    {
        perror("写入文件失败");
        return -1;
    }

    int res = write(fd, mfile->buf, mfile->datalength);
    if (res < 0)
    {
        perror("writing failed");
        return -1;
    }
    return 0;
}
int Server::DealLogonFunction(char *buffer, int socket)
{
    Logon *logon = (Logon *)buffer;
    char query[512] = {0};
    int nbytes = 0;

    Answer answer;
    try
    {
        // select * from users where username = %s and password = %s
        // // 执行一条查询语句
        Statement *stmt = con->createStatement();
        sprintf(query, "select * from users where username=\"%s\"", logon->username);
        puts(query);

        ResultSet *res = stmt->executeQuery(query);
        Answer answer;
        answer.cmd = CMD_LOGON_ANSWER;

        while (res->next())
        {
            //
            // puts("TEST");
            // std::cout << res->getString("username") << res->getString("password") << std::endl;
            if (strcmp(res->getString("password").c_str(), logon->password) == 0)
            {
                puts("success");
                answer.answer = true;
                printf("%s登陆成功\n", res->getString("username").c_str());
                sprintf(answer.reason, "登录成功");
                OnLineUserList tuser;
                tuser.socket = socket;
                sprintf(tuser.username, "%s", logon->username);
                // tuser.username = logon->username;

                _clientSockfds.push_back(tuser);
                // this->users_map<logon->username> = socket;
            }
            else
            {
                answer.answer = false;
                sprintf(answer.reason, "密码不正确");
            }
            nbytes = send(socket, &answer, MSG_LENGTH, 0);
            if (nbytes < 0)
            {
                perror("sending failed");
                return -1;
            }
        }

        delete res;
        delete stmt;
    }
    catch (SQLException &e)
    {
        std::cout << "SQLException: " << e.getErrorCode() << " " << e.what() << std::endl;
        answer.answer = false;
        sprintf(answer.reason, "%s", e.what());
        nbytes = send(socket, &answer, MSG_LENGTH, 0);
        if (nbytes < 0)
        {
            perror("sending failed");
            return -1;
        }
    }
    // try
    // {
    //     // select * from users where username = %s and password = %s
    //     // // 执行一条查询语句
    //     Statement *stmt = con->createStatement();
    //     sprintf(query, "select * from %s ", logon->username);
    //     puts(query);
    //     ResultSet *res = stmt->executeQuery(query);

    //     while (res->next())
    //     {
    //         printf("msg:\t");
    //         puts(res->getString("msg").c_str());
    //     }

    // }
    // catch (SQLException &e)
    // {

    // }

    return 0;
}
void Server::DealRequstAddFriend(char *pbuffer,int socket)
{
    MSG_ADD *msg = (MSG_ADD*)pbuffer;
    
    try
    {

        char query[512];
        // // 执行一条查询语句
        memset(query, 0, 512);
        Statement *stmt = con->createStatement();
        //DealGetUser();
        // insert into user_info VALUES();
        //Deal
        char pic[64]={0};
        char nick_name[64]={0};
        char signame[64]={0};
        DealGetUser(pic,msg->username1,nick_name,signame);
        sprintf(query, "insert into %s VALUES(\"%s\",\"%s\",\"%s\",\"/%s\",\"%s\")", msg->username1,msg->username2,nick_name,signame,pic,"");
        puts(query);
        ResultSet *res = stmt->executeQuery(query);

        delete res;
        delete stmt;
    }
    catch (SQLException &e)
    {
        std::cout << "SQLException: " << e.getErrorCode() << " " << e.what() << std::endl;
    }
     try
    {

        char query[512];
        // // 执行一条查询语句
        memset(query, 0, 512);
        Statement *stmt = con->createStatement();
        // insert into user_info VALUES();
        char pic[64]={0};
        char nick_name[64]={0};
        char signame[64]={0};
        DealGetUser(pic,msg->username2,nick_name,signame);
        sprintf(query, "insert into %s VALUES(\"%s\",\"%s\",\"%s\",\"%s\",\"%s\")", msg->username2,msg->username1,nick_name,signame,pic,"");
    //    sprintf(query, "insert into %s VALUES(\"administrator\",\"administator\",\"I am god\",\"/new/prefix1/res/img/01.png\")", msg->username2);
        puts(query);
        ResultSet *res = stmt->executeQuery(query);

        delete res;
        delete stmt;
    }
    catch (SQLException &e)
    {
        std::cout << "SQLException: " << e.getErrorCode() << " " << e.what() << std::endl;
    }
}

int Server::DealRequestList(char *buffer, int socket)
{

    puts("request test");
    Request *user = (Request *)buffer;
    char query[1024] = {0};
    Answer answer;

    answer.cmd = CMD_REG_USERINFO_ANSWER;
    int nbytes = 0;

    try
    {
        // // 执行一条查询语句

        Statement *stmt = con->createStatement();

        sprintf(query, "select * from %s", user->username);
        //  sprintf(query, "insert into user_info VALUES('%s','%s','%s','%s')", user->username, user->nickname, user->signature, user->path);

        puts(query);
        ResultSet *res = stmt->executeQuery(query);
        while (res->next())
        {
            UserInfo userlist;
            userlist.cmd = CMD_ANSWER_FRIENDLIST;

            sprintf(userlist.username, "%s", res->getString("username").c_str());
            sprintf(userlist.nickname, "%s", res->getString("nickname").c_str());
            sprintf(userlist.signature, "%s", res->getString("signame").c_str());
            sprintf(userlist.path, "%s", res->getString("offlinemsg").c_str());
            puts(userlist.username);
            puts(userlist.nickname);
            puts(userlist.signature);
            puts(userlist.path);

            nbytes = send(socket, &userlist, MSG_LENGTH, 0);
            if (nbytes < 0)
            {
                perror("sending failed");
                return -1;
            }
            else
                printf("%d发送成功\n", nbytes);
        }
        delete res;
        delete stmt;
    }
    catch (SQLException &e)
    {
        std::cout << "SQLException: " << e.getErrorCode() << " " << e.what() << std::endl;
    }

    return 0;
}

int Server::DealChatToFriend(char *buffer, int socket)
{
    ChatPackage *pack = (ChatPackage *)buffer;
    pack->msg_type = 0;

    char conetent[MSG_LENGTH] = {0};
    for (int i = 0; i < _clientSockfds.size(); i++)
    {
        if (strncmp(_clientSockfds[i].username, pack->to, strlen(pack->to)) == 0)
        {
            int nbytes = send(_clientSockfds[i].socket, buffer, MSG_LENGTH, 0);
            if (nbytes < 0)
            {
                perror("sending failed");
                return -1;
            }
            return 0;
        }
    }
    try
    {
        puts("test");
        // // 执行一条查询语句
        char query[1100] = {0};
        Statement *stmt = con->createStatement();
        puts(pack->to);
        puts(pack->msgbody);
        puts(pack->from);
        // insert into user_info VALUES();
        // printf("UPDATE  \"%s\" SET offlinemsg = \"\" where username = \"%s\"\n    ", pack->to,pack->from);
        sprintf(query, "UPDATE  %s SET msg = \"%s\" where username = \"%s\"", pack->to, pack->msgbody, pack->from);
        printf("offto:   \n");
        puts(query);
        ResultSet *res = stmt->executeQuery(query);

        delete res;
        delete stmt;
    }
    catch (SQLException &e)
    {
        std::cout << "SQLException: " << e.getErrorCode() << " " << e.what() << std::endl;
    }

    return 0;
}
void Server::DealGetUser(char *pbuffer,const  char *name,char * nbuffer ,char * ibuffer)
{
    char query[512]={0};
    try
    {
        // select * from users where username = %s and password = %s
        // // 执行一条查询语句
        Statement *stmt = con->createStatement();
        sprintf(query, "select * from user_info where username=\"%s\"", name);
        puts(query);

        ResultSet *res = stmt->executeQuery(query);
        Answer answer;
        answer.cmd = CMD_LOGON_ANSWER;

        while (res->next())
        {
            if(nbuffer)
            {
                
                strcpy(nbuffer,res->getString("nickname").c_str());


            }
            if(ibuffer)
            {
                strcpy(ibuffer,res->getString("signature").c_str());
            }
            strcpy(pbuffer,res->getString("picture_path").c_str());
            printf("deal:");

            puts(pbuffer);
        }
    }
    catch (SQLException &e)
    {

    }
}

void Server::DealUnknownMsg(char *buffer)
{
    memset(buffer, 0, MSG_LENGTH);
    puts("收到未知消息");
}

void Server::DealGetMsg(char *buffer, int socket)
{
    GetMsg *getmsg = (GetMsg *)buffer;
    char query[512] = {0};
    int nbytes = 0;

    AnswerMsg answer;
    answer.datalength = 0;
    answer.cmd = CMD_GET_MSG;
    try
    {
        // select * from users where username = %s and password = %s
        // // 执行一条查询语句
        Statement *stmt = con->createStatement();
        sprintf(query, "select * from %s ", getmsg->username);
        puts(query);
        ResultSet *res = stmt->executeQuery(query);

        while (res->next())
        {
            printf("msg:\t");
            puts(res->getString("msg").c_str());
            if (res->getString("msg").length() == 0)
            {
                puts("line");
            }
            else
            {
                answer.datalength++;
               // static int pos = 0;
               *answer.pic = ':';
                // if(getmsg->cmd == CMD_GET_MSG_ADDFRIEND)
                // {
                    
                // }
                if(strcmp(res->getString("msg").c_str(),"addfrined")==0)
                {
                    strcpy(answer.pic+1,"/new/prefix1/res/img/notice.png");
                    //strcpy(answer.,"/new/prefix1/res/img/notice.png");
                }
                else DealGetUser(answer.pic+1,res->getString("username").c_str());
                strcpy(answer.username,res->getString("username").c_str());
                strcpy(answer.msgbody, res->getString("msg").c_str());
                //pos += res->getString("msg").length()+1;
                //printf("length:%d\n", pos);
            }
        }

        int nbytes = send(socket, &answer, MSG_LENGTH, 0);
        if (nbytes < 0)
        {
            perror("sending failed");
        }
        else
            printf("answer firend msg%d发送成功\n", nbytes);
    }
    catch (SQLException &e)
    {
        // int nbytes = send(socket, &answer, MSG_LENGTH, 0);
        // if (nbytes < 0)
        // {
        //     perror("sending failed");
        // }
        // else
        //     printf("answer firend msg%d发送成功\n", nbytes);
    }
}

int Server::OnRun()
{
    if (IsRun())
    {
        fd_set readfds, tmpfds;
        FD_ZERO(&readfds);
        FD_ZERO(&tmpfds);
        FD_SET(0, &readfds);
        FD_SET(_serverSocket, &readfds);
        int maxfd = _serverSocket;
        char buffer[MSG_LENGTH] = {0};
        struct timeval tval = {1, 0};
        while (1)
        {
            tmpfds = readfds;

            select(maxfd + 1, &tmpfds, NULL, NULL, &tval);
            if (FD_ISSET(_serverSocket, &tmpfds))
            {

                int _clientSockfd = Accept();
                puts("有新客户端加入");
                FD_SET(_clientSockfd, &readfds);
                if (maxfd < _clientSockfd)
                    maxfd = _clientSockfd;

                //_clientSockfds.push_back(_clientSockfd);
            }

            for (int i = 4; i <= maxfd; i++)
            {
                if (FD_ISSET(i, &tmpfds))
                {
                    int result = recv(i, buffer, MSG_LENGTH, MSG_DONTWAIT);
                    if (result == 0)
                    {
                        printf("客户端%d已退出\n", i);
                        close(i);
                        FD_CLR(i, &readfds);
                        if (i == maxfd)
                            maxfd--;
                    }
                    else
                    {
                        // 先取出数据头

                        DataHeader *header = (DataHeader *)buffer;
                        switch (header->cmd)
                        {
                        case CMD_LOGIN:
                            DealLoginFunction(buffer, i);
                            break;
                        case CMD_LOGON:
                            DealLogonFunction(buffer, i);
                            break;
                        case CMD_REG_USERINFO:
                            DealRegInfoFunction(buffer, i);
                            break;
                        case CMD_REQUEST_USERINFO:
                            DealRequestUserinfo(buffer, i);
                            break;
                        case CMD_REQUEST_FRIENDSLIST:
                            DealRequestList(buffer, i);
                            break;
                        case CMD_CHAT_TO_FRIEND:
                            DealChatToFriend(buffer, i);
                            break;
                        case CMD_GET_MSG:
                            DealGetMsg(buffer, i);
                            break;
                        case CMD_ADD_FRIEND_TO_LIST:
                            DealRequstAddFriend(buffer,i);
                            break;
    

                        // case CMD_GET_MSG_ADDFRIEND:
                        //     DealGetMsg(buffer, i);

                        // case CMD_TRANS_FILE:
                        //     DealBigFile(buffer, i);
                        //     break;
                        default:
                            DealUnknownMsg(buffer);
                            break;
                        }
                        puts("处理完了一条消息");
                        // if (header->cmd == CMD_LOGIN)
                        // {
                        //     DealLoginFunction(buffer, i);
                        // }
                    }
                }
            }
        }
    }
    return 0;
}

int Server::Connect2DB()
{

    try
    {
        driver = get_driver_instance();
        con = driver->connect("tcp://127.0.0.1:3306", "debian-sys-maint", "0XNuWDfAbUjxwCv4");

        // 连接到test数据库
        con->setSchema("chat");

        // // 执行一条查询语句
        // Statement *stmt = con->createStatement();
        // ResultSet *res = stmt->executeQuery("insert into users VALUES(0,\"administrator\",\"123456\",1))");
        // while (res->next())
        // {
        //     std::cout << res->getString("name") << std::endl;
        // }
    }
    catch (SQLException &e)
    {
        std::cout << "SQLException: " << e.getErrorCode() << " " << e.what() << std::endl;
        return -1;
    }
    printf("connecting success\n");
    return 0;
}

Server::~Server()
{
    if (con)
    {
        delete con;
    }
    if (_serverSocket > 0)
        close(_serverSocket);
}
